// 确保在Windows平台下包含必要的库文件
#ifdef _WIN32
    #pragma comment(lib, "ws2_32.lib")  // 链接Windows Socket库(ws2_32.lib)
#endif

// 包含Windows套接字编程所需的头文件
#include <winsock2.h>  // 必须在其他Windows头文件之前包含
#include <stdio.h>

// 定义缓冲区长度为1024字节
#define BUFF_LENGTH 1024

int main()
{
    // 初始化Windows套接字环境,使用2.2版本
    WSADATA wsa_Data;
    WSAStartup(MAKEWORD(2, 2), &wsa_Data);

    // 创建服务器套接字,使用TCP协议
    SOCKET server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server_socket == INVALID_SOCKET)
    {
        printf("socket failed\n");
        WSACleanup(); // 添加清理
        return 1;
    }

    // 配置服务器地址结构体
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;                     // 使用IPv4地址族
    server_addr.sin_port = htons(8080);                   // 设置端口号为8080,需要进行网络字节序转换
    // server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置IP地址为本地回环地址(localhost)
    server_addr.sin_addr.s_addr = INADDR_ANY;

    // 将套接字绑定到指定的IP地址和端口
    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
    {
        printf("bind failed\n");
        closesocket(server_socket); // 添加关闭socket
        WSACleanup();
        return 1;
    }

    // 开始监听连接请求,设置最大等待连接队列长度为5
    if (listen(server_socket, 5) == SOCKET_ERROR)
    {
        printf("listen failed\n");
        closesocket(server_socket);
        WSACleanup();
        return 1;
    }

    printf("server is running on port 8080\n");

    // 服务器主循环,持续接受客户端连接
    while (1)
    {
        // 接受客户端的连接请求,返回新的套接字用于与该客户端通信
        SOCKET client_socket = accept(server_socket, NULL, NULL);
        if (client_socket == INVALID_SOCKET)
        {
            printf("accept failed\n");
            closesocket(server_socket);
            WSACleanup();
            return 1;
        }

        printf("client connected\n");

        // 定义接收数据的缓冲区和长度变量
        char buffer[BUFF_LENGTH];
        int recv_len;

        // 持续接收当前客户端发送的数据
        while ((recv_len = recv(client_socket, buffer, BUFF_LENGTH, 0)) > 0)
        {
            // 在接收到的数据末尾添加字符串结束符'\0'
            buffer[recv_len] = '\0';
            printf("received: %s\n", buffer);

            // 将接收到的数据原样发送回客户端(回显服务)
            if (send(client_socket, buffer, recv_len, 0) == SOCKET_ERROR)
            {
                printf("send failed\n");
                break;
            }
        }

        // 关闭与当前客户端的连接
        closesocket(client_socket);
        printf("client disconnected\n");
    }

    // 关闭服务器套接字并清理Windows套接字环境
    closesocket(server_socket);
    WSACleanup();
    return 0;
}
